<?php

/*
	Class: Commerce_Magento_Catalog

	About: Author
		Tyler Vigeant

	About: License
		<http://communit.as/docs/license>
*/
class Magento_Curl_Cart extends Commerce_Db_Model_Magento {
	
	public $debug_mode = false;
	public $locale_code = '';
	
	protected $sid = false;
	protected $primary_url = 'checkout/cart/';
	protected $user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)';
	
	private $_scheme = NULL;
	private $_host	 = NULL;
	private $_locale = NULL;
	
	public function __construct(){
		$this->session = new Zend_Session_Namespace('Default');
		if( isset($this->session->magento_curl_session_id) ){
			if( is_array($this->session->magento_curl_session_id) ){
				## If there is an array of session id's default to the first one until the locale is specified.
				$copy = $this->session->magento_curl_session_id;	reset($copy);
				$this->sid = current($copy);
			} else {
				$this->sid = $this->session->magento_curl_session_id;
			}
		}
		
		$this->_scheme = Cts_Registry::get('magento_curl_scheme');
		$this->_host = Cts_Registry::get('magento_curl_host');
	}
	
	public function setLocale( $code ){
		if( Cts_Registry::get('magento_curl_locale_code')=='1' && !empty($code) ){
			$Catalog = new CommerceMagentoCatalog();
			
$code = $Catalog->formatStoreId( $code );
if( $code!='en_us' && $code!='fr_fr' && $code!='de_de' ){
	Cts_Log::report("Magento Cart CURL passed an invalid locale of {$code}", NULL, Zend_Log::ERR);
	$code = 'en_us';
}
			
			$this->_locale = $Catalog->formatStoreId( $code );
			
			## Set the class to use (or aquire) the correct session for this locale
			$copy = $this->session->magento_curl_session_id;
			if( is_array($copy) && !array_key_exists($this->_locale, $copy) ){
				## Force _curl() to pull a new session for this locale
				$this->sid = false;
			} elseif( is_array($copy) && array_key_exists($this->_locale, $copy) ){
				## Set the session to this locale
				$this->sid = $copy[ $this->_locale ];
			}
		} else {
			$this->_locale = NULL;
		}
	}
	
	protected function _curl( $url, $post=NULL ){
		if($this->debug_mode) echo "<pre>Parsing URL: {$url}</pre>";
		
		## Parse URL
		$url = parse_url($url);
		
		## Override input with config variables
		$url['scheme'] = $this->_scheme;
		$url['host'] = $this->_host;
		
		## Add locale code
		if( !is_null($this->_locale) ){
			$url['host'] = $url['host'].'/'.$this->_locale;
		}
		
		## Parse Query
		if( isset($url['query']) ){
			parse_str($url['query'], $url['query']);
		} else {
			$url['query'] = array();
		}
		
		## Set the CURL theme override
		$url['query']['force_curl'] = 'curl';
		
		## Check for session id
		if( !empty($this->sid) ){
			if( !array_key_exists('SID', $url['query']) ){
				$url['query']['SID'] = $this->sid;
			}
		}
		
		## Rebuild Query
		$url['query'] = http_build_query( $url['query'] );
		
		## Rebuild URL
		$curl_url  = $url['scheme'] .'://'. $url['host'] .'/'. $url['path'];
		$curl_url .= (!empty($url['query'])) ? "?{$url['query']}" : '';
		
		if($this->debug_mode) echo "<pre>Connecting to: <a href=\"{$curl_url}\" target=\"_blank\">{$curl_url}</a></pre>";
		
		## Start CURL
		$ch = curl_init(); 
		
		## Set Options
		//curl_setopt($ch, CURLOPT_MUTE,				true); 
		curl_setopt($ch, CURLOPT_URL,				$curl_url); 
		curl_setopt($ch, CURLOPT_HEADER,			false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,	true);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION,	false);
		curl_setopt($ch, CURLOPT_USERAGENT,			$this->user_agent);
		curl_setopt($ch, CURLOPT_HTTPAUTH, 			CURLAUTH_ANY);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 	false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 	2);
		
		## Add POST Data
		if( !is_null($post) ){
			curl_setopt($ch, CURLOPT_POST,			true); 
			curl_setopt($ch, CURLOPT_POSTFIELDS,	$post);
			if($this->debug_mode){
				echo "<pre>Adding post data: \n";
				parse_str($post, $decode);
				var_dump( $decode );
				echo "</pre>";
			}
		}
		
		## Run CURL
		$curl_return = curl_exec($ch);
		$curl_info = curl_getinfo($ch);
		curl_close($ch);
		
		## Return
		if( $curl_return !== false ){
			if($this->debug_mode) echo "<pre>CURL returned status {$curl_info['http_code']} in {$curl_info['total_time']} seconds</pre>";
			
			switch( $curl_info['http_code'] ){
				case 200:
					$unserialize = @unserialize($curl_return);
					if( !is_array($unserialize) ){
						if($this->debug_mode){
							echo "<pre>CURL results could not be unserialized.\nCURL Results:\n";
							var_dump($curl_return);
							echo '</pre>';
						}
						
						return $curl_return;
					} else {
						if($this->debug_mode){
							echo "<pre>CURL Results:\n";
							var_dump($unserialize);
							echo '</pre>';
						}
						
						if( empty($this->sid) && is_array($unserialize) && isset($unserialize['session_id']) ){
							$this->sid = $unserialize['session_id'];
							
							## If locale is turned on, set a locale specific session ID for Magento
							if( Cts_Registry::get('magento_curl_locale_code')=='1' && !empty($this->_locale) ){
								$locale_session = array( $this->_locale=>$unserialize['session_id'] );
								
								if(!is_array($this->session->magento_curl_session_id)){
									$this->session->magento_curl_session_id = $locale_session;
								} else {
									$this->session->magento_curl_session_id = array_merge($this->session->magento_curl_session_id, $locale_session);
								}
							} else {
								$this->session->magento_curl_session_id = $unserialize['session_id'];
							}
						}
						return $unserialize;
					}
					break;
					
				case 404:
					Cts_Log::report("404 Page Not Found when attempting to CURL {$curl_info['url']}", NULL, Zend_Log::ERR);
					return false;
					break;
				
				case 500:
					Cts_Log::report("500 Internal Server Error when attempting to CURL {$curl_info['url']}", NULL, Zend_Log::ERR);
					return false;
					break;
			}
		}
		
		Cts_Log::report("An unknown error has occured when attempting to CURL {$curl_info['url']}", NULL, Zend_Log::ERR);
		return false;
	}
	
	public $items		= array();
	public $num_items	= 0;
	public $total		= 0.0;
	public $subtotal	= 0.0;
	public $urls		= array();
	
	public function getCartData(){
		if($this->debug_mode) echo "<pre style=\"font-weight: bold;\">:: Getting current cart item data ::</pre>";
		
		$data = $this->_curl('checkout/cart');
		
		if( is_array($data) && !empty($data) ){
			if( isset($data['urls']) ){
				$this->urls = $data['urls'];
			}
			if( isset($data['cart_products']) ){
				$this->items = $data['cart_products'];
				foreach( $this->items as $item ){
					$this->num_items += $item['qty'];
				}
			}
			
			if( isset($data['totals']['grand_total']) ){
				$this->total = number_format($data['totals']['grand_total'], 2, '.', '');
			} else {
				$this->total = (isset($data['cart_total'])) ? number_format($data['cart_total'], 2, '.', '') : '0.0000';
			}
			
			if( isset($data['totals']['discount']) ){
				$this->discount = number_format($data['totals']['discount'], 2, '.', '');
			} else {
				$this->discount = '0.00';
			}
			
			if( isset($data['totals']['subtotal']) ){
				$this->subtotal = number_format($data['totals']['subtotal'], 2, '.', '');
			} else {
				$this->subtotal = (isset($data['cart_subtotal'])) ? number_format($data['cart_subtotal'], 2, '.', '') : '0.0000';
			}
			
			
			return true;
		} else {
			return false;
		}
	}
	
	public function addProduct( $product_id, $qty=1, $args=false, $related=false ){
		if($this->debug_mode) echo "<pre style=\"font-weight: bold;\">:: Adding product to the cart ::</pre>";
		
		$post = array();
		$post['qty'] = $qty;
		if($related) $post['related_product'] = $related;
		if($args)	 $post['super_attribute'] = $args;
		
		## Prep post and get data for CURL
		$post = http_build_query($post);
		$uenc = base64_encode( $this->_scheme.'://'.$this->_host.'/catalog/product/view/id/'.$product_id );
		$curl_url = 'checkout/cart/add/uenc/'.$uenc.'/product/'.$product_id.'/';
		
		## Attempt to add the product
		$this->_curl( $curl_url, $post );
		
		## Check to see if it was added
		$this->getCartData();
		
		if( is_array($this->items) && !empty($this->items) ){
			end($this->items);
			$last_item = current($this->items);
			reset($this->items);
			
			return ($last_item['product_id'] == $product_id);
		} else {
			return false;	
		}
	}
	
	public function updateProduct( $id, $args, $is_product_id=NULL ){
		$this->getCartData();
		
		if($this->debug_mode) echo "<pre style=\"font-weight: bold;\">:: Updating product (quantity) ::</pre>";
		
		if( is_array($this->items) && !empty($this->items) ){
			## Search through the cart items to find a cart item ID using a product ID
			if( $is_product_id===true || !array_key_exists($id, $this->items) ){
				$item_found = false;
				foreach( $this->items as $item_id=>$item ){
					if( $item['product_id'] == $id ){
						$item_found = true;
						$id = $item_id;
						break;
					}
				}
				
				## Could not find the product in the cart
				if( $item_found===false ){
					return false;
				}
			}
			
			## Correct quantities sent as an integer
			if( is_int($args) || is_string($args) ){
				$args = array( 'qty'=>number_format($args,0) );
			}
			
			if($this->debug_mode && (int)$args['qty']==0) echo "<pre style=\"color: #ff0000;\">Quantity is zero. The product will be removed from the cart.</pre>";
			
			## Update cart item
			$post = array($id=>$args);
			$post = http_build_query( array('cart'=>$post) );
			$curl_url = 'checkout/cart/updatePost/';
			$this->_curl( $curl_url, $post );
			
			## Assume it worked to save loading time. This is poor programming.
			return true;
		} else {
			return false;	
		}
	}
	
	public function removeProduct( $id ){
		if($this->debug_mode) echo "<pre style=\"font-weight: bold;\">:: Removing product from the cart ::</pre>";
		
		## Magento has it's own URL to remove products, however simply setting the quantity to zero saves development time.
		return $this->updateProduct( $id, array('qty'=>'0'), false );
	}
	
	public function emptyCart(){
		$this->getCartData();
		
		if($this->debug_mode) echo "<pre style=\"font-weight: bold;\">:: Removing all products from the cart ::</pre>";
		
		if( is_array($this->items) && !empty($this->items) ){
			$post = array();
			foreach( $this->items as $item_id=>$item ){
				$post[ $item_id ] = array('qty'=>'0');
			}
			
			$post = http_build_query( array('cart'=>$post) );
			$curl_url = 'checkout/cart/updatePost/';
			$this->_curl( $curl_url, $post );
		}
		
		## This method will assign the Communitas visitor a new Magento session, but it will leave their original session intact.
		## This may be useful for resetting a visitors cart when changing locales, but keeping their old cart available should they switch back.
		//$this->session = new Zend_Session_Namespace('Cts_Temp');
		//$this->session->magento_curl_session_id = NULL;
		
		return true;
	}
}
